﻿using System;
using System.Collections.Generic;
using System.Linq;
using EasyWeixin.Entities.JsonResult;

using RaceList.activity.util;

namespace RaceList.activity.help
{
    /// <summary>
    ///     这里主要是封装了一些数据库中对Activity_Relay,Activity_SubRelay的操作
    /// </summary>
    public partial class RelayQuery
    {
        //这个DbContext一定不要使用static的，因为这样不能获取到最新的数据，这是我最大的败笔啊
        //static ipowdb_suibian_webDataContext db = ConnHelper.ipowdb_suibian_web();
        public static void UpdateRelaySumScore(int relayId, double sumScore)
        {
            ipowdb_suibian_webDataContext db = ConnHelper.ipowdb_suibian_web();
            Activity_Relay relay = db.Activity_Relay.Where(s => s.Id == relayId).FirstOrDefault();
            if (relay != null)
            {
                relay.SumScore = sumScore;
                db.SubmitChanges();
            }
        }

        public static Activity_Relay GetRelay(int relayId)
        {
            ipowdb_suibian_webDataContext db = ConnHelper.ipowdb_suibian_web();
            Activity_Relay result = db.Activity_Relay.FirstOrDefault(s => s.Id == relayId);
            return result;
        }

        public static WeixinUser GetWeixinUser(int weixinUserId)
        {
            ipowdb_suibian_webDataContext db = ConnHelper.ipowdb_suibian_web();
            WeixinUser result = db.WeixinUser.FirstOrDefault(s => s.Id == weixinUserId);
            if (result == null)
                throw new Exception("weixinUserId查找WeixinUser为空");
            return result;
        }

        /// <summary>
        ///     必须是当前正在进行的活动
        ///     根据微信UserId获取用户成绩最好的记录
        /// </summary>
        /// <param name="weixinUserId"></param>
        /// <returns></returns>
        public static Activity_Relay GetBestScore(int weixinUserId, int cycleId)
        {
            ipowdb_suibian_webDataContext db = ConnHelper.ipowdb_suibian_web();
            WeixinUser weixinuser = db.WeixinUser.Where(s => s.Id == weixinUserId).FirstOrDefault();
            IEnumerable<Activity_Relay> list = weixinuser.Activity_Relay.Where(s => s.CycleId == cycleId);
            //list = UpdateBestScore(list);
            list = list.Where(s => s.SumScore <= ActivityConfig.MHalloweenMaxScore).OrderByDescending(s => s.SumScore);
            return list.FirstOrDefault();
        }

        private static IEnumerable<Activity_Relay> UpdateBestScore(IEnumerable<Activity_Relay> list)
        {
            list = list.Where(s => s.Activity_SubRelay.Count != 4);
            foreach (Activity_Relay item in list)
            {
                double sumScore = GetSumScoreById(item.Id);
                UpdateRelaySumScore(item.Id, sumScore);
            }
            return list;
        }

        public static List<Activity_Relay> GetRelayList()
        {
            ipowdb_suibian_webDataContext db = ConnHelper.ipowdb_suibian_web();
            return db.Activity_Relay.ToList();
        }

        public static List<Activity_Relay> GetRelayList(int weixinUserId)
        {
            ipowdb_suibian_webDataContext db = ConnHelper.ipowdb_suibian_web();
            IQueryable<Activity_Relay> result = db.Activity_Relay.Where(s => s.WeixinUserId == weixinUserId);
            return result.ToList();
        }

        /// <summary>
        ///     获取总成绩排名
        ///     已自动获取了用户所有成绩中最高成绩的记录，
        ///     也就是同一个用户多次玩的其他的成绩被排除了
        /// </summary>
        /// <param name="num">前几名</param>
        /// <param name="maxScore">最大成绩上限</param>
        /// <param name="isNeedGameOver"></param>
        /// <returns></returns>
        public static List<Activity_Relay> GetPaihang(int num = 10, double maxScore = double.MaxValue, bool isNeedGameOver = false)
        {
            ipowdb_suibian_webDataContext db = ConnHelper.ipowdb_suibian_web();
            var result = new List<Activity_Relay>();

            if (db.Activity_Relay.Count() < num)
                num = db.Activity_Relay.Count();

            var list = db.Activity_Relay.AsQueryable();
            if (isNeedGameOver)
            {
                list = db.Activity_Relay.Where(s => s.IsGameOver);
            }

            IQueryable<IGrouping<int, Activity_Relay>> groups =
                list.Where(s => s.SumScore <= maxScore).GroupBy(s => s.WeixinUserId);
            foreach (var item in groups)
            {
                //先将用户分组,然后排序，取用户成绩最高的那条记录
                //2.取每个分组中成绩最高的那个
                result.Add(item.OrderByDescending(s => s.SumScore).First());
            }
            //3.将所有成绩排序后然后取前10名
            //4.成绩相同的按完成时间排名
            result = result.OrderByDescending(s => s.SumScore)
                .ThenBy(s => s.EditTime)
                .Take(num).ToList();
            return result;
        }

        public static int GetMingci(Activity_Relay relay)
        {
            var alllist = GetPaihang(int.MaxValue).Select(s => s.Id).ToList();
            var result = alllist.IndexOf(relay.Id) + 1;
            return result;
        }
        public static double GetBaifenbi(Activity_Relay relay)
        {
            var baifenbi = (double)0;
            var alllist = GetPaihang(int.MaxValue).Select(s => s.Id).ToList();
            var result = alllist.IndexOf(relay.Id) + 1;
            int beforeme = result - 1; //成绩在我前面的
            int sum = alllist.Count; //所有的总成绩
            if (beforeme == 0)
            {
                baifenbi = 100.0;
            }
            else
            {
                var num = Math.Round(beforeme / (double)sum, 3); //预防 .0000001这种情况
                if (num == 0.0)
                {
                    baifenbi = .999;
                }
                else
                {
                    baifenbi = 1 - num;
                }
                baifenbi = baifenbi * 100;
            }
            return baifenbi;
        }
        public static int GetMingciById(int relayId, double maxScore = double.MaxValue)
        {
            List<Activity_Relay> list = GetPaihang(int.MaxValue);
            if (list == null)
                return 1;

            Activity_Relay relay = list.FirstOrDefault(s => s.Id == relayId);
            if (relay == null)
                throw new Exception("relayId查找Activity_Relay为空");
            int result = list.IndexOf(relay);
            list = null;
            return result + 1;
        }

        public static WeixinUser AddWeixinUser(OAuthWeixinUserInfoResult oAuthWeixinUser)
        {
            ipowdb_suibian_webDataContext db = ConnHelper.ipowdb_suibian_web();
            WeixinUser weixinUser = db.WeixinUser.FirstOrDefault(s => s.OpenId == oAuthWeixinUser.openid);
            if (weixinUser != null)
                return weixinUser;

            weixinUser = new WeixinUser
            {
                AddDate = DateTime.Now,
                City = oAuthWeixinUser.city,
                Country = oAuthWeixinUser.country,
                Headimgurl = oAuthWeixinUser.headimgurl,
                Language = "",
                Nickname = oAuthWeixinUser.nickname,
                OpenId = oAuthWeixinUser.openid,
                Privilege = oAuthWeixinUser.privilege.ToString(),
                Province = oAuthWeixinUser.province,
                Remark = "",
                Sex = oAuthWeixinUser.sex,
                Subscribe = 0,
                SubscribeTime = 0,
                Unionid = "",
                UpdateDate = DateTime.Now
            };

            db.WeixinUser.InsertOnSubmit(weixinUser);
            db.SubmitChanges();
            return weixinUser;
        }

        public static Activity_Relay AddRelay(Activity_Relay relay)
        {
            ipowdb_suibian_webDataContext db = ConnHelper.ipowdb_suibian_web();
            db.Activity_Relay.InsertOnSubmit(relay);
            db.SubmitChanges();
            return relay;
        }

        /// <summary>
        ///     本来应该是可以更新SumScore字段的啊，但是为什么有的时候不能呢？
        ///     添加子表的时候，已经顺便更新了主表中的sumscore字段
        /// </summary>
        /// <param name="subRelay"></param>
        public static void AddSubRelay(Activity_SubRelay subRelay)
        {
            ipowdb_suibian_webDataContext db = ConnHelper.ipowdb_suibian_web();
            db.Activity_SubRelay.InsertOnSubmit(subRelay);

            Activity_Relay relay = db.Activity_Relay.FirstOrDefault(s => s.Id == subRelay.RelayId);
            if (relay == null)
                throw new Exception("添加subRelay时查找Activity_Relay为空");

            //更新主表sumscore字段
            relay.SumScore = GetSumScoreById(relay.Id) + subRelay.Score;

            relay.IsGameOver = GetHelps(relay).Count() + 1 >= ActivityConfig.MHalloweenTotalPerson;

            relay.EditTime = DateTime.Now;

            db.SubmitChanges();
        }

        /// <summary>
        ///     如果数据超过4个，取时间（正序先来先得）排序的前4条
        ///     某个特定活动中分享的好友集合
        /// </summary>
        /// <param name="relay"></param>
        /// <returns></returns>
        public static List<Help> GetHelps(Activity_Relay relay)
        {
            var result = new List<Help>();
            result.Add(new Help
            {
                HeadUrl = relay.WeixinUser.Headimgurl,
                Score = relay.Score,
                WeixinUserid = relay.WeixinUserId
            });
            List<Activity_SubRelay> list = relay.Activity_SubRelay.OrderBy(s => s.AddTime).ToList(); //按照先来后到的顺序来排列成绩
            if (list.Count > 4)
            {
                list = list.Take(ActivityConfig.MHalloweenTotalPerson - 1).ToList(); //这个MHalloweenTotalPerson包括了自己，所以字表中减去1；
                //需要更新下主表的SumScore,并删除多余的subrelay数据

                #region 在获取有误的情况下，及时的更正的了信息,

                double sumScore = list.Sum(s => s.Score);
                UpdateRelaySumScore(relay.Id, sumScore);
                List<Activity_SubRelay> delList = relay.Activity_SubRelay.OrderByDescending(s => s.AddTime).ToList();
                int length = delList.Count;
                int takeNum = length - (ActivityConfig.MHalloweenTotalPerson - 1); //留下后面几条，前面的都是多余的
                delList = delList.Take(takeNum).ToList();

                DeleteSubRelay(delList);

                #endregion
            }

            foreach (Activity_SubRelay item in list)
            {
                result.Add(new Help
                {
                    HeadUrl = item.WeixinUser.Headimgurl ?? "",
                    Score = item.Score,
                    WeixinUserid = item.WeixinUserId
                });
            }
            return result;
        }

        /// <summary>
        ///     这是为了解决，某些情况下添加了多余的字表数据
        /// </summary>
        /// <param name="list"></param>
        private static void DeleteSubRelay(List<Activity_SubRelay> list)
        {
            ipowdb_suibian_webDataContext db = ConnHelper.ipowdb_suibian_web();
            foreach (Activity_SubRelay item in list)
            {
                Activity_SubRelay subRelay = db.Activity_SubRelay.FirstOrDefault(s => s.Id == item.Id);
                if (subRelay == null)
                    continue;
                db.Activity_SubRelay.DeleteOnSubmit(subRelay);
            }
            db.SubmitChanges();
        }

        /// <summary>
        ///     判断某个微信用户能否帮忙
        /// </summary>
        /// <param name="weixinUserId">需要验证的用户的openId</param>
        /// <param name="relay">某个活动的Id</param>
        /// <returns>true表示能帮忙</returns>
        public static bool GetCanHelp(int weixinUserId, Activity_Relay relay)
        {
            bool result = true;
            List<int> helpedlist = GetHelps(relay.WeixinUserId);
            if (helpedlist.Contains(weixinUserId))
            {
                result = false;
            }
            helpedlist = null;
            return result;
        }

        /// <summary>
        ///     这个的使用情况应该是给在每次帮忙跑的时候更新子表的时候需要重新sumscore，并更新到主表
        ///     根据id获取当前用户的总成绩，在每次需要统计用户信息的时候需要修改下这个字段的
        /// </summary>
        /// <param name="relayId"></param>
        /// <returns></returns>
        public static double GetSumScoreById(int relayId)
        {
            Activity_Relay relay = GetRelay(relayId);

            double result = relay.Activity_SubRelay.Sum(s => s.Score);
            result += relay.Score;
            return result;
        }

        /// <summary>
        ///     所有游戏中，分享给的所有好友
        ///     找到某个微信用户所有玩过的游戏，然后查找素有的分享过的好友
        /// </summary>
        /// <param name="weixinUserId"></param>
        /// <returns></returns>
        public static List<int> GetHelps(int weixinUserId)
        {
            ipowdb_suibian_webDataContext db = ConnHelper.ipowdb_suibian_web();
            var result = new List<int>();
            IQueryable<Activity_Relay> list = db.Activity_Relay.Where(s => s.WeixinUserId == weixinUserId);
            foreach (Activity_Relay item in list)
            {
                IEnumerable<int> listsub = item.Activity_SubRelay.Select(s => s.WeixinUser.Id);
                result.AddRange(listsub);
            }
            return result;
        }
    }
}